#include "camera.h"
#include "matrix.h"
#include "vector3.h"
#include "algebra.h"

using namespace krryn::system;
using namespace krryn::math;
using namespace krryn::view;

// negative speed moves backwards
void camera_fps::move(float a_Speed){
	math::vector3f l_Direction = m_Target - m_Position;

	m_Position.m_X += l_Direction.m_X * a_Speed;
	m_Position.m_Z += l_Direction.m_Z * a_Speed;

	m_Target.m_X += l_Direction.m_X * a_Speed;
	m_Target.m_Z += l_Direction.m_Z * a_Speed;
}

void camera_fps::strafe(float a_Speed){
	math::vector3f l_Direction = m_Target - m_Position;

	m_Position.m_X -= l_Direction.m_Z * a_Speed;
	m_Position.m_Z += l_Direction.m_X * a_Speed;

	m_Target.m_X -= l_Direction.m_Z * a_Speed;
	m_Target.m_Z += l_Direction.m_X * a_Speed;
}

void camera_fps::rotate(float a_Speed){
	math::vector3f l_Direction = m_Target - m_Position;

	m_Target.m_Z = m_Position.m_Z + sin(a_Speed) * l_Direction.m_X
		+ cos(a_Speed) * l_Direction.m_Z;

	m_Target.m_X = m_Position.m_X + cos(a_Speed) * l_Direction.m_X
		- sin(a_Speed) * l_Direction.m_Z;
}

matrix camera_fps::view_matrix() const{
	const math::vector3f l_AxisZ = (m_Target - m_Position).normalize();
	const math::vector3f l_AxisX = m_Up.cross(l_AxisZ);
	const math::vector3f l_AxisY = l_AxisX.cross(l_AxisZ);

	matrix l_LookAtMatrix;

	l_LookAtMatrix[0] = l_AxisX.m_X;
	l_LookAtMatrix[1] = l_AxisX.m_Y;
	l_LookAtMatrix[2] = l_AxisX.m_Z;

	l_LookAtMatrix[4] = l_AxisY.m_X;
	l_LookAtMatrix[5] = l_AxisY.m_Y;
	l_LookAtMatrix[6] = l_AxisY.m_Z;

	l_LookAtMatrix[8] = l_AxisZ.m_X;
	l_LookAtMatrix[9] = l_AxisZ.m_Y;
	l_LookAtMatrix[10] = l_AxisZ.m_Z;

	l_LookAtMatrix.invert();

	l_LookAtMatrix[3] = m_Position.m_X;
	l_LookAtMatrix[7] = m_Position.m_Y;
	l_LookAtMatrix[11] = m_Position.m_Z;

	return l_LookAtMatrix;
}

void camera_fps_controller_default::update(float a_DeltaTime){
	float l_Speed = m_LinearSpeed * a_DeltaTime;
	float l_RotationSpeed = degree_to_radian(m_AngularSpeed * a_DeltaTime);

	if(m_Keyboard->key_pressed('w')){
		m_Camera->move(l_Speed);
	}

	if(m_Keyboard->key_pressed('s')){
		m_Camera->move(-l_Speed);
	}

	if(m_Keyboard->key_pressed('a')){
		m_Camera->strafe(-l_Speed);
	}

	if(m_Keyboard->key_pressed('d')){
		m_Camera->strafe(l_Speed);
	}

	//if(m_Input->key_pressed(key_left)){
	//	rotate(-l_RotationSpeed);
	//}

	//if(m_Input->key_pressed(key_right)){
	//	rotate(l_RotationSpeed);
	//}
}

//
//void camera_fps::update(float a_DeltaTime){
//	float l_Speed = 40.f * a_DeltaTime;
//	float l_RotationSpeed = degree_to_radian(30.f * a_DeltaTime);
//
//	if(m_Input->key_down(key_w) || m_Input->key_down(key_up)){
//			move(l_Speed);
//	}
//
//	if(m_Input->key_down(key_s) || m_Input->key_down(key_down)){
//			move(-l_Speed);
//	}
//
//	if(m_Input->key_down(key_a)){
//		strafe(-l_Speed);
//	}
//
//	if(m_Input->key_down(key_d)){
//		strafe(l_Speed);
//	}
//
//	if(m_Input->key_down(key_left)){
//		rotate(-l_RotationSpeed);
//	}
//
//	if(m_Input->key_down(key_right)){
//		rotate(l_RotationSpeed);
//	}
//}
//
//void camera_fps::update_mouse(int a_SceenWidth, int a_SceenHeight){
//	point l_Position = m_Input->get_mouse_pos_abs();
//
//	// reset the mouse so we get relative coordinates, in pixels
//	m_Input->set_mouse_pos_abs(a_SceenWidth / 2, a_SceenHeight / 2);
//
//	float l_MouseSpeed = 500;
//	float l_MaxDifference = 8;
//
//	float l_AngleY = ((a_SceenWidth / 2) - l_Position.m_X) / l_MouseSpeed;
//	float l_AngleZ = ((a_SceenHeight / 2) - l_Position.m_Y) / l_MouseSpeed;
//
//	m_Target.m_Y += l_AngleZ * 2;
//
//	if(m_Target.m_Y - m_Position.m_Y > l_MaxDifference)
//		m_Target.m_Y = m_Position.m_Y + l_MaxDifference;
//
//	if(m_Target.m_Y - m_Position.m_Y < -l_MaxDifference)
//		m_Target.m_Y = m_Position.m_Y - l_MaxDifference;
//
//	rotate(-l_AngleY);
//}
//